<div class="loading-footer {shown ? '' : 'hidden'}">
  <div class="loading-wrapper {showLoading ? 'shown' : ''}"
       aria-hidden={!showLoading}
  >
    <!-- Sapper's mousemove event listener schedules style recalculations for the loading spinner in
         Chrome because it's always animating, even when hidden. So disable animations when not visible
         to avoid this. -->
    <LoadingSpinner size={48} animate={showLoading} />
    <span class="loading-footer-info">
      {intl.loadingMore}
    </span>
  </div>
  <div class="button-wrapper {showLoadButton ? 'shown' : ''}"
       aria-hidden={!showLoadButton}
  >
    <button type="button"
            class="primary"
            on:click="onClickLoadMore(event)">
      {intl.loadMore}
    </button>
  </div>
</div>
<style>
  .loading-footer {
    padding: 20px 0;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  .loading-wrapper {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s linear;
  }
  .loading-wrapper.shown {
    opacity: 1;
    pointer-events: auto;
  }
  .loading-footer-info {
    margin-left: 20px;
    font-size: 1.3em;
  }
  .button-wrapper {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: none;
  }
  .button-wrapper.shown {
    opacity: 1;
    pointer-events: auto;
    transition: opacity 0.2s linear 0.2s;
  }
</style>
<script>
  import { observe } from 'svelte-extras'
  import LoadingSpinner from '../LoadingSpinner.html'
  import { store } from '../../_store/store.js'
  import { fetchMoreItemsAtBottomOfTimeline } from '../../_actions/timeline.js'
  import { announceAriaLivePolite } from '../../_utils/announceAriaLivePolite.js'

  const SCREEN_READER_ANNOUNCE_DELAY = 1000 // 1 second

  export default {
    oncreate () {
      // If the new statuses are delayed a significant amount of time, announce to screen readers that we're loading
      let delayedAriaAnnouncementHandle

      this.observe('showLoading', showLoading => {
        if (showLoading) {
          delayedAriaAnnouncementHandle = setTimeout(() => {
            delayedAriaAnnouncementHandle = undefined
            announceAriaLivePolite('intl.loadingMore')
          }, SCREEN_READER_ANNOUNCE_DELAY)
        } else if (delayedAriaAnnouncementHandle) {
          clearTimeout(delayedAriaAnnouncementHandle)
        }
      })
    },
    store: () => store,
    computed: {
      shown: ({ $timelineInitialized, $runningUpdate, $disableInfiniteScroll }) => (
        $timelineInitialized && ($disableInfiniteScroll || $runningUpdate)
      ),
      showLoading: ({ $runningUpdate }) => $runningUpdate,
      showLoadButton: ({ $runningUpdate, $disableInfiniteScroll }) => !$runningUpdate && $disableInfiniteScroll
    },
    methods: {
      observe,
      onClickLoadMore (e) {
        e.preventDefault()
        e.stopPropagation()
        const { currentInstance, currentTimeline } = this.store.get()
        /* no await */ fetchMoreItemsAtBottomOfTimeline(currentInstance, currentTimeline)
        // focus the last item in the timeline; it makes the most sense to me since the button disappears
        try {
          // TODO: should probably expose this as an API on the virtual list instead of reaching into the DOM
          const virtualListItems = document.querySelector('.virtual-list').children
          const lastItem = virtualListItems[virtualListItems.length - 2] // -2 because the footer is last
          lastItem.querySelector('article').focus()
        } catch (e) {
          console.error(e)
        }
      }
    },
    components: {
      LoadingSpinner
    }
  }
</script>
